package kz.pompei.ifacer.main;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.metal.MetalTabbedPaneUI;

import kz.pompei.ifacer.cursor_manager.CursorManager;
import kz.pompei.ifacer.cursor_manager.def.DefCursorManager;
import kz.pompei.ifacer.grot.GrotPanel;
import kz.pompei.ifacer.grot.acts.ActContainer;
import kz.pompei.ifacer.util.Handler;
import kz.pompei.ifacer.util.HandlerList;
import kz.pompei.ifacer.visio.Visio;
import kz.pompei.ifacer.visio.skin.Skin;
import kz.pompei.ifacer.visio.skin.SkinGetter;
import kz.pompei.ifacer.visio.skin.SkinVisio;

public class GrotTabPanel extends JTabbedPane {
  
  public final HandlerList updates = new HandlerList();
  
  public GrotTabPanel() {
    {
      JPanel ppp = new JPanel();
      ppp.setName("plusPanel");
      
      ppp.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
          createTab();
        }
      });
      
      addTab("+", ppp);
    }
    
    setUI(new MetalTabbedPaneUI() {
      @Override
      protected MouseListener createMouseListener() {
        return new MouseAdapter() {
          @Override
          public void mousePressed(MouseEvent e) {
            final int index = getUI().tabForCoordinate(GrotTabPanel.this, e.getX(), e.getY());
            
            if (index != -1) {
              if (SwingUtilities.isLeftMouseButton(e)) {
                if (getSelectedIndex() != index) {
                  setSelectedIndex(index);
                } else if (isRequestFocusEnabled()) {
                  requestFocusInWindow();
                }
              }
            }
          }
        };
      }
    });
    
    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON2) {
          int index = getUI().tabForCoordinate(GrotTabPanel.this, e.getX(), e.getY());
          if (index < 0) return;
          Component com = getComponentAt(index);
          if (com instanceof GrotPanel) {
            GrotPanel grot = (GrotPanel)com;
            if (grot.canClose()) {
              remove(index);
              updates.fire();
            }
          }
          return;
        }
        if ("plusPanel".equals(getSelectedComponent().getName())) {
          createTab();
          return;
        }
      }
    });
    
    updates.add(new Handler() {
      @Override
      public void handle() throws Exception {
        for (int i = 0, C = getTabCount(); i < C; i++) {
          Component com = getComponentAt(i);
          if (com instanceof GrotPanel) {
            GrotPanel grot = (GrotPanel)com;
            if (grot.workingFile == null) {
              setTitleAt(i, "Unknown");
              continue;
            }
            String fileName = grot.workingFile.getName();
            if (grot.actContainer.modified()) {
              fileName = "*" + fileName;
            }
            String ext = ".iface.xml";
            if (fileName.endsWith(ext)) {
              fileName.substring(fileName.length() - ext.length(), fileName.length());
            }
            setTitleAt(i, fileName);
          }
        }
      }
    });
    
    addChangeListener(new ChangeListener() {
      @Override
      public void stateChanged(ChangeEvent e) {
        updates.fire();
      }
    });
  }
  
  private Skin skin = new Skin();
  
  private final Visio visio = new SkinVisio(new SkinGetter() {
    @Override
    public Skin get() {
      return skin;
    }
  });
  
  private final CursorManager cursorManager = new DefCursorManager();
  
  private void createTab() {
    addNewAndSelect(newGrot());
  }
  
  public void addNewAndSelect(GrotPanel grot) {
    int selectedIndex = getSelectedIndex();
    insertGrot(grot, selectedIndex);
    setSelectedIndex(selectedIndex);
    updates.fire();
    grot.actContainer.updates.add(updates.handler());
  }
  
  private void insertGrot(GrotPanel grot, int toIndex) {
    insertTab("grotPanel", null, grot, null, toIndex);
  }
  
  private void addGrot(GrotPanel grot) {
    int lastIndex = -1;
    for (int i = 0, C = getTabCount(); i < C; i++) {
      Component com = getComponentAt(i);
      if (com instanceof GrotPanel) {
        lastIndex = i;
      }
    }
    insertTab("grotPanel", null, grot, null, lastIndex + 1);
    updates.fire();
    grot.actContainer.updates.add(updates.handler());
  }
  
  public GrotPanel getActiveGrot() {
    Component com = getSelectedComponent();
    if (com == null) return null;
    if (com instanceof GrotPanel) return (GrotPanel)com;
    return null;
  }
  
  public List<GrotPanel> getGrotList() {
    List<GrotPanel> ret = new ArrayList<>();
    for (int i = 0, C = getTabCount(); i < C; i++) {
      Component com = getComponentAt(i);
      if (com instanceof GrotPanel) {
        ret.add((GrotPanel)com);
      }
    }
    return ret;
  }
  
  public GrotPanel newGrot() {
    return new GrotPanel(new ActContainer(), visio, cursorManager);
  }
  
  public void openFile(File file) throws Exception {
    GrotPanel grot = newGrot();
    grot.load(new FileInputStream(file));
    grot.workingFile = file;
    grot.actContainer.fix();
    addGrot(grot);
  }
}
